#include "vzconn/conn/ipcserver.h"
#include "vzconn/base/helper.h"
#include "vzconn/conn/ipcconnect.h"

#ifndef WIN32
#include <stdio.h>
#include <unistd.h>
#endif

namespace vzconn {

#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
IpcServer::IpcServer(boost::asio::io_service &io_service,
                     const std::string addr,
                     uint16 port)
  : VzServer(io_service),
    stop_(false) {
  ipc_file_ = NetAddrToIpcAddr(addr, port);
}

IpcServer::~IpcServer() {
}

bool IpcServer::Start() {
  if (stop_) {
    LOG(ERROR) << "The IpcServer is not stop, you should not Start agian";
    return false;
  }
  try {
    remove(ipc_file_.c_str());
    acceptor_.reset(new boost::asio::local::stream_protocol::acceptor(
                      io_service_,
                      boost::asio::local::stream_protocol::endpoint(ipc_file_)));
    // TODO BUG?
    stop_ = false;
    io_service_.post(
      boost::bind(&VzServer::WaitNextConnect, shared_from_this()));
  } catch (std::exception& e) {
    LOG(ERROR) << e.what();
    return false;
  }
  return true;
}

const std::string IpcServer::bind_addr() const {
  return ipc_file_;
}

void IpcServer::WaitNextConnect() {
  if (stop_) {
    LOG(WARNING) << "The IpcServer was stoped";
    return;
  }
  if (!acceptor_) {
    LOG(ERROR) << "The Acceptor is null";
    return;
  }

  IpcConnect *conn = new IpcConnect(io_service_);
  VzConnect::Ptr vz_connect(conn);
  acceptor_->async_accept(conn->socket(),
                          boost::bind(&IpcServer::HandleAcceptor,
                                      shared_from_this(),
                                      vz_connect,
                                      boost::asio::placeholders::error));
}

void IpcServer::HandleStopVzServer() {
  if (acceptor_->is_open()) {
    acceptor_->close();
  }
}
#endif
}